﻿
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using Adalbertus.BudgetPlanner.Domain;
using Caliburn.Micro;
using System.Collections.Specialized;

namespace Adalbertus.BudgetPlanner.ViewModels.BudgetPlanning
{
    public class BudgetPlanVM : PropertyChangedBase
    {
        //public event EventHandler DetailRemoved;

        private BudgetPlan _wrappedBudgetPlan;
        public BudgetPlan WrappedBudgetPlan
        {
            get
            {
                Contract.Ensures(Contract.Result<BudgetPlan>() != null);
                return _wrappedBudgetPlan;
            }
        }

        public BudgetPlanVM(BudgetPlan plan)
        {
            Contract.Requires<ArgumentNullException>(plan != null);
            _wrappedBudgetPlan = plan;

            _details = new BindableCollectionExt<BudgetPlanDetailVM>();
            _details.PropertyChanged   += BudgetPlanDetailVMPropertyChanged;
            _details.CollectionChanged += DetailsCollectionChanged;

            IEnumerable<BudgetPlanDetailVM> budgetPlanDetails =
                WrappedBudgetPlan.Details.Select(x => new BudgetPlanDetailVM(x));
            _details.AddRange(budgetPlanDetails);
        }

        private void DetailsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                    NotifyOfPropertyChange(() => TotalValue);
                    NotifyOfPropertyChange(() => Details);
                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                    BudgetPlanDetailVM detail = (e.OldItems[0] as BudgetPlanDetailVM);
                    if (detail == null)
                    {
                        throw new InvalidOperationException("Unable to remove detail from budget plan - detail info is empty.");
                    }
                    WrappedBudgetPlan.Remove(detail.WrappedBudgetPlanDetail);
                    //if (DetailRemoved != null)
                    //{
                    //    DetailRemoved(detail, new EventArgs());
                    //}
                    NotifyOfPropertyChange(() => TotalValue);
                    NotifyOfPropertyChange(() => Details);
                    break;
            }
        }

        private void BudgetPlanDetailVMPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "Value":
                    NotifyOfPropertyChange(() => TotalValue);
                    NotifyOfPropertyChange(() => Details);
                    break;
                case "Description":
                    NotifyOfPropertyChange(() => Details);
                    break;
            }
        }

        public string Name
        {
            get
            {
                if (WrappedBudgetPlan.Flow.Saving == null)
                {
                    return WrappedBudgetPlan.Flow.Name;
                }
                else
                {
                    return string.Format("{0} [{1}]", WrappedBudgetPlan.Flow.Name, WrappedBudgetPlan.Flow.Description);
                }

            }
        }

        public decimal TotalValue
        {
            get { return Details.Sum(x => x.Value); }
        }

        private decimal _newDetailValue;
        public decimal NewDetailValue
        {
            get { return _newDetailValue; }
            set
            {
                _newDetailValue = value;
                NotifyOfPropertyChange(() => NewDetailValue);
                NotifyOfPropertyChange(() => CanAddDetail);
            }
        }

        private string _newDetailDescription;
        public string NewDetailDescription
        {
            get { return _newDetailDescription; }
            set
            {
                _newDetailDescription = value;
                NotifyOfPropertyChange(() => NewDetailDescription);
            }
        }

        private bool _isNewDetailValueFocused;
        public bool IsNewDetailValueFocused
        {
            get { return _isNewDetailValueFocused; }
            set
            {
                _isNewDetailValueFocused = value;
                NotifyOfPropertyChange(() => IsNewDetailValueFocused);
            }
        }

        public bool CanAddDetail
        {
            get
            {
                return NewDetailValue > 0;
            }

        }

        private BindableCollectionExt<BudgetPlanDetailVM> _details;
        public BindableCollectionExt<BudgetPlanDetailVM> Details
        {
            get
            {
                Contract.Ensures(Contract.Result<BindableCollectionExt<BudgetPlanDetailVM>>() != null);
                return _details;
            }
        }

        public void AddDetail()
        {
            BudgetPlanDetail detail = WrappedBudgetPlan.AddDetail(NewDetailValue, NewDetailDescription);
            BudgetPlanDetailVM budgetPlanDetailVM = new BudgetPlanDetailVM(detail);
            budgetPlanDetailVM.PropertyChanged += (s, e) => { NotifyOfPropertyChange(() => Details); };
            Details.Add(budgetPlanDetailVM);
            NewDetailValue = 0;
            NewDetailDescription = string.Empty;

            SetDefaultFocus();
        }

        public void SetDefaultFocus()
        {
            IsNewDetailValueFocused = false;
            IsNewDetailValueFocused = true;
        }
    }
}
